package fr.lteconsulting.hexa.client.ui.dialog; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.core.shared.GWT; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.MouseDownEvent; import com.google.gwt.event.dom.client.MouseDownHandler; import com.google.gwt.event.dom.client.MouseMoveEvent; import com.google.gwt.event.dom.client.MouseMoveHandler; import com.google.gwt.event.dom.client.MouseUpEvent; import com.google.gwt.event.dom.client.MouseUpHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.resources.client.ImageResource; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.ComplexPanel; import com.google.gwt.user.client.ui.ProvidesResize; import com.google.gwt.user.client.ui.RequiresResize; import com.google.gwt.user.client.ui.RootLayoutPanel; import com.google.gwt.user.client.ui.Widget; import fr.lteconsulting.hexa.client.ui.resources.image.ImageResources; class ResizablePanelBad extends ComplexPanel implements MouseMoveHandler, MouseUpHandler, MouseDownHandler, RequiresResize, ProvidesResize { private Widget contentWidget = null; int resizeHandlerSize = 5; int titleSize; static final int LEFT = 1; static final int TOP = 2; static final int RIGHT = 4; static final int BOTTOM = 8; static final int MOVE = 16; int minWidth = 800; int minHeight = 500; Element topLeft; Element top; Element topRight; Element right; Element bottomRight; Element bottom; Element bottomLeft; Element left; Element content; Element title; Element close; boolean fResizing = false; int direction = 0; int startX; int startY; int startTop; int startLeft; int startWidth; int startHeight; static final String template = "<div class='top_left_handler' style='position: absolute; left:0px; top:0px; width:#HANDLER_SIZE#px; height:#HANDLER_SIZE#px;'></div>" + "<div class='top_handler' style='position: absolute; left:#HANDLER_SIZE#px; top:0px; right:#HANDLER_SIZE#px; height:#HANDLER_SIZE#px;'></div>" + "<div class='top_right_handler' style='position: absolute; width:#HANDLER_SIZE#px; top:0px; right:0px; height:#HANDLER_SIZE#px;'></div>" + "<div class='right_handler' style='position: absolute; width:#HANDLER_SIZE#px; top:#HANDLER_SIZE#px; right:0px; bottom:#HANDLER_SIZE#px;'></div>" + "<div class='bottom_right_handler' style='position: absolute; width:#HANDLER_SIZE#px; height:#HANDLER_SIZE#px; right:0px; bottom:0px;'></div>" + "<div class='bottom_handler' style='position: absolute; left:#HANDLER_SIZE#px; height:#HANDLER_SIZE#px; right:#HANDLER_SIZE#px; bottom:0px;'></div>" + "<div class='bottom_left_handler' style='position: absolute; left:0px; height:#HANDLER_SIZE#px; width:#HANDLER_SIZE#px; bottom:0px;'></div>" + "<div class='left_handler' style='position: absolute; left:0px; top:#HANDLER_SIZE#px; width:#HANDLER_SIZE#px; bottom:#HANDLER_SIZE#px;'></div>" + "<div class='title' style='overflow:hidden; position: absolute; left:#HANDLER_SIZE#px; top:#HANDLER_SIZE#px; right:#TITLE_RIGHT#px; height:#TITLE_SIZE#px;'></div>" + "<div class='close_button' style='position: absolute; width:#TITLE_SIZE#px; top:#HANDLER_SIZE#px; right:#HANDLER_SIZE#px; height:#TITLE_SIZE#px;'><img></img></div>" + "<div class='content' style='overflow:auto; position: absolute; left:#HANDLER_SIZE#px; top:#CONTENT_TOP#px; right:#HANDLER_SIZE#px; bottom:#HANDLER_SIZE#px;'></div>"; public ResizablePanelBad( String titleText, Widget contentWidget ) { Element main = DOM.createDiv(); setElement( main ); setStylePrimaryName( ResizablePanel.CSS.main() ); ImageResource closeImage = ImageResources.INSTANCE.close(); titleSize = Math.max( closeImage.getHeight(), closeImage.getWidth() ) + 5; String html = template.replaceAll( "#HANDLER_SIZE#", "" + resizeHandlerSize ).replaceAll( "#TITLE_SIZE#", "" + titleSize ).replaceAll( "#CONTENT_TOP#", "" + (resizeHandlerSize + titleSize) ).replaceAll( "#TITLE_RIGHT#", "" + (resizeHandlerSize + titleSize) ); main.setInnerHTML( html ); topLeft = (Element) main.getChild( 0 ); top = (Element) main.getChild( 1 ); topRight = (Element) main.getChild( 2 ); right = (Element) main.getChild( 3 ); bottomRight = (Element) main.getChild( 4 ); bottom = (Element) main.getChild( 5 ); bottomLeft = (Element) main.getChild( 6 ); left = (Element) main.getChild( 7 ); title = (Element) main.getChild( 8 ); close = (Element) main.getChild( 9 ).getChild( 0 ); close.setAttribute( "src", closeImage.getSafeUri().asString() ); content = (Element) main.getChild( 10 ); addDomHandler( this, MouseMoveEvent.getType() ); addDomHandler( this, MouseUpEvent.getType() ); addDomHandler( this, MouseDownEvent.getType() ); title.setInnerText( titleText ); this.contentWidget = contentWidget; } public void setText( String titleText ) { title.setInnerText( titleText ); } public void setContent( Widget w ) { if( contentWidget != null ) remove( contentWidget ); contentWidget = w; add( w, content ); } Glass glass; public void show( boolean isModal, boolean isAutoHide ) { // try to auto size the dialog, based on the content size, mais ca marche pas ... :( if( contentWidget != null ) { Scheduler.get().scheduleDeferred( new ScheduledCommand() { @Override public void execute() { // try to fit to the content size int maxWidth = Window.getClientWidth() - 20; // 20 pixels of // margin int w = Math.max( ResizablePanelBad.this.getOffsetWidth(), Math.max( contentWidget.getElement().getScrollWidth(), contentWidget.getElement().getOffsetWidth() ) ) + resizeHandlerSize * 2; if( w > maxWidth ) w = maxWidth; int maxHeight = Window.getClientHeight() - 20; int h = Math.max( ResizablePanelBad.this.getOffsetHeight(), Math.max( contentWidget.getElement().getScrollHeight(), contentWidget.getElement().getOffsetHeight() ) ) + resizeHandlerSize * 2 + titleSize; if( h > maxHeight ) h = maxHeight; PositionAndSize posSize = new PositionAndSize( (Window.getClientWidth() - w) / 2, (Window.getClientHeight() - h) / 2, w, h ); posSize.limit(); RootLayoutPanel.get().setWidgetLeftWidth( ResizablePanelBad.this, posSize.left, Unit.PX, posSize.width, Unit.PX ); RootLayoutPanel.get().setWidgetTopHeight( ResizablePanelBad.this, posSize.top, Unit.PX, posSize.height, Unit.PX ); RootLayoutPanel.get().animate( 300 ); } } ); } if( isModal ) { glass = new Glass(); RootLayoutPanel.get().add( glass ); } RootLayoutPanel.get().add( this ); int screenWidth = RootLayoutPanel.get().getOffsetWidth(); int screenHeight = RootLayoutPanel.get().getOffsetHeight(); int width = 400; int height = 230; PositionAndSize posSize = new PositionAndSize( (screenWidth - width) / 2, (screenHeight - height) / 2, width, height ); posSize.limit(); RootLayoutPanel.get().setWidgetLeftWidth( this, posSize.left, Unit.PX, posSize.width, Unit.PX ); RootLayoutPanel.get().setWidgetTopHeight( this, posSize.top, Unit.PX, posSize.height, Unit.PX ); RootLayoutPanel.get().animate( 300 ); } public void hide() { RootLayoutPanel.get().remove( this ); if( glass != null ) { RootLayoutPanel.get().remove( glass ); glass = null; } } @Override public void onMouseDown( MouseDownEvent event ) { direction = getDirection( event.getNativeEvent().getEventTarget() ); if( direction == 0 ) return; startX = event.getScreenX(); startY = event.getScreenY(); startLeft = ResizablePanelBad.this.getAbsoluteLeft(); startTop = ResizablePanelBad.this.getAbsoluteTop(); startWidth = ResizablePanelBad.this.getOffsetWidth(); startHeight = ResizablePanelBad.this.getOffsetHeight(); DOM.setCapture( getElement() ); fResizing = true; event.stopPropagation(); event.preventDefault(); } @Override public void onMouseMove( MouseMoveEvent event ) { if( !fResizing ) return; updateSize( event.getNativeEvent().getEventTarget(), event.getScreenX() - startX, event.getScreenY() - startY ); event.stopPropagation(); event.preventDefault(); } @Override public void onMouseUp( MouseUpEvent event ) { if( !fResizing ) return; updateSize( event.getNativeEvent().getEventTarget(), event.getScreenX() - startX, event.getScreenY() - startY ); DOM.releaseCapture( getElement() ); fResizing = false; event.stopPropagation(); event.preventDefault(); } private int getDirection( Object source ) { if( source == top ) return TOP; else if( source == topRight ) return TOP + RIGHT; else if( source == right ) return RIGHT; else if( source == bottomRight ) return RIGHT + BOTTOM; else if( source == bottom ) return BOTTOM; else if( source == bottomLeft ) return BOTTOM + LEFT; else if( source == left ) return LEFT; else if( source == topLeft ) return TOP + LEFT; else if( source == title ) return MOVE; return 0; } private void updateSize( Object source, int devX, int devY ) { if( direction == MOVE ) { PositionAndSize posSize = new PositionAndSize( startLeft + devX, startTop + devY, startWidth, startHeight ); posSize.limit(); RootLayoutPanel.get().setWidgetLeftWidth( ResizablePanelBad.this, posSize.left, Unit.PX, posSize.width, Unit.PX ); RootLayoutPanel.get().setWidgetTopHeight( ResizablePanelBad.this, posSize.top, Unit.PX, posSize.height, Unit.PX ); return; } if( (direction & LEFT) == LEFT ) { PositionAndSize posSize = new PositionAndSize( startLeft + devX, startTop, startWidth - devX, startHeight ); posSize.limit(); RootLayoutPanel.get().setWidgetLeftWidth( ResizablePanelBad.this, posSize.left, Unit.PX, posSize.width, Unit.PX ); } if( (direction & RIGHT) == RIGHT ) { PositionAndSize posSize = new PositionAndSize( startLeft, startTop, startWidth + devX, startHeight ); posSize.limit(); RootLayoutPanel.get().setWidgetLeftWidth( ResizablePanelBad.this, posSize.left, Unit.PX, posSize.width, Unit.PX ); } if( (direction & TOP) == TOP ) { PositionAndSize posSize = new PositionAndSize( startLeft, startTop + devY, startWidth, startHeight - devY ); posSize.limit(); RootLayoutPanel.get().setWidgetTopHeight( ResizablePanelBad.this, posSize.top, Unit.PX, posSize.height, Unit.PX ); } if( (direction & BOTTOM) == BOTTOM ) { PositionAndSize posSize = new PositionAndSize( startLeft, startTop, startWidth, startHeight + devY ); posSize.limit(); RootLayoutPanel.get().setWidgetTopHeight( ResizablePanelBad.this, posSize.top, Unit.PX, posSize.height, Unit.PX ); } } @Override public void onResize() { int left = ResizablePanelBad.this.getAbsoluteLeft(); int top = ResizablePanelBad.this.getAbsoluteTop(); int width = ResizablePanelBad.this.getOffsetWidth(); int height = ResizablePanelBad.this.getOffsetHeight(); PositionAndSize posSize = new PositionAndSize( left, top, width, height ); boolean needAdjustment = posSize.limit(); if( needAdjustment ) { GWT.log( "onResize => re-resize !" ); RootLayoutPanel.get().setWidgetLeftWidth( ResizablePanelBad.this, posSize.left, Unit.PX, posSize.width, Unit.PX ); RootLayoutPanel.get().setWidgetTopHeight( ResizablePanelBad.this, posSize.top, Unit.PX, posSize.height, Unit.PX ); return; } for( Widget child : getChildren() ) { if( child instanceof RequiresResize ) { ((RequiresResize) child).onResize(); } } } private class PositionAndSize { int top; int left; int width; int height; public PositionAndSize( int left, int top, int width, int height ) { this.top = top; this.left = left; this.width = width; this.height = height; } // ensure that the position and size fits in the screen // returns false if something has been changed boolean limit() { boolean res = true; int screenHeight = Window.getClientHeight(); int screenWidth = Window.getClientWidth(); // adjust horizontally // limit left position if( left < 0 ) { left = 0; res = false; } int maxLeft = screenWidth - minWidth; if( left > maxLeft ) { left = maxLeft; res = false; } // limit width if( width < minWidth ) { width = minWidth; res = false; } int maxWidth = screenWidth - width; if( width > maxWidth ) { width = maxWidth; res = false; } // adjust vertically // limit top position if( top < 0 ) { top = 0; res = false; } int maxTop = screenHeight - minHeight; if( top > maxTop ) { top = maxTop; res = false; } // limit height if( height < minHeight ) { height = minHeight; res = false; } int maxHeight = screenHeight - top; if( height > maxHeight ) { height = maxHeight; res = false; } return res; } } public HandlerRegistration addCloseClickHandler( final ClickHandler handler ) { return addDomHandler( new ClickHandler() { @Override public void onClick( ClickEvent event ) { if( (Object) event.getNativeEvent().getEventTarget() != (Object) close ) return; handler.onClick( event ); } }, ClickEvent.getType() ); } } class Glass extends Widget { public Glass() { setElement( Document.get().createDivElement() ); getElement().setAttribute( "isGlass", "true" ); getElement().getStyle().setBackgroundColor( "rgba(0, 0, 0, 0.6)" ); } }